#pragma once
#ifndef MESSAGE_H
#define MESSAGE_H
#include <malloc.h>
#include <stdlib.h> 
#include <memory.h>
#include <string.h>
#include <string>
#include <iostream>
#include <mutex>
#include<list>
#include<memory>
#include<map>
#include<queue>
//#define MEM_NUM  4*1024
#define MAX_MEM_NUM  30*10
#define MAX_MSG_LEN  2*1024 
#define MAX_THD 10 //

#pragma pack(push 1)
class CMemoryBlock
{
protected:
	unsigned char*  _pBuff;
	//�ڴ������С
	unsigned int    _buffSize;
	//ʹ�ô�С
	unsigned int    _buffRealSize;
public:
	CMemoryBlock(CMemoryBlock& b){
		_buffSize = 0;
		allocbuff(b.buffsize());
		copy(b.buffhead(),b.realbuffsize());
		_buffRealSize = b.realbuffsize();
	}
	CMemoryBlock(const unsigned int size){
		_buffSize = 0;
		allocbuff(size);
		_buffRealSize = 0;
	}
	CMemoryBlock(void){
		_pBuff = nullptr;
		_buffRealSize = 0;
		_buffSize = 0;
	}
	virtual ~CMemoryBlock(void){
		resetbuff();
	}
public:
		unsigned int GetBufSize(){
		return buffsize();
	}

	unsigned int GetRealBufSize(){
		return realbuffsize();
	}

	unsigned char* GetBufHead(){
		return buffhead();
	}

	unsigned char * CopyData( const unsigned char* pData,unsigned int nLen/*=0*/ )
	{
		return copy(pData,nLen);
	}

	void Clear()
	{
		clear();
	}

	unsigned char * AddCopyData( const unsigned char* pData,unsigned int nLen/*=0*/)
	{
		return addcopy(pData,nLen);
	}


private:
	//���������
	//�����������ڶ����ڲ���һ���ڴ棬ʹ��ʱ��ȥ����һ�飬ʹ����ɺ���Ҫ�ͷš�
	//�Ѿ����仺���ͷָ��
	unsigned char* buffhead() const{
		if (_buffSize == 0)
			return nullptr;
		return _pBuff;
	}
	//�Ѿ�����Ļ���Ĵ�С��
	unsigned int buffsize() const{
		return _buffSize;
	}
	//����ʹ�ô�С
	unsigned int realbuffsize() const{
		return _buffRealSize;
	}
	//�����������ó��ض���ֵ��
	void setbuffvalue(int n){
		memset(_pBuff, n, _buffSize);
	}

	//���ⲿ�������ݵ�����
	unsigned char* copy(const unsigned char* pData, unsigned int nLen = 0){
		if (nLen == 0 && _buffSize == 0||pData==nullptr)
			return nullptr;
		//���Ȳ����Ļ�����䡣
		if (_buffSize<nLen)
			if (!allocbuff(nLen + _buffRealSize)){
				return nullptr;
			}
		_buffRealSize = nLen;
		memcpy(_pBuff, pData, (nLen == 0) ? _buffSize : nLen);
		return _pBuff;
	}
	unsigned char* addcopy(const unsigned char* pData, unsigned int nLen = 0){
		if (pData == nullptr){
			return nullptr;
		}
		if (nLen == 0){
			return _pBuff;
		}

		//���Ȳ���������䡣
		if (_buffSize < nLen + _buffRealSize) {

			if (!allocbuff(nLen + _buffRealSize))
			{
				return nullptr;
			}
		}
		memcpy(_pBuff + _buffRealSize, pData, nLen);
		_buffRealSize = nLen + _buffRealSize;
		return _pBuff;
	}

	//���仺�沢���ػ����ͷָ�롣���ؿ������ʧ�ܡ�
	unsigned char* allocbuff(unsigned int nNeededSize){
		if (_buffSize >= nNeededSize)
			return buffhead();

		if (_buffSize != 0)
			_pBuff = (unsigned char*)realloc(_pBuff, nNeededSize);
		else
			_pBuff = (unsigned char*)malloc(nNeededSize);

		//m_buffRealSize = nNeededSize;
		_buffSize = nNeededSize;
		if (nullptr == _pBuff){//�����ڴ�ʧ�ܡ�
			_buffRealSize = 0;
			_buffSize = 0;
			return nullptr;
		}
		return buffhead();
	}
	//���û��棬�˷����ᵼ�»�����������ڴ汻ǿ����ա�
	bool resetbuff(){
		if (_buffSize != 0)
		{
			free(_pBuff);
			_pBuff = nullptr;
			_buffRealSize = 0;
		}
		_buffSize = 0;
		return true;
	}
	//��ջ��棬��������ͷ��ڴ棬ֻ�ǽ�buffersize��Ϊ0
	bool clear(){
		if(_buffSize>0&&_pBuff!=nullptr)
		memset(_pBuff, 0, _buffSize);
		_buffRealSize = 0;
		//resetbuff();
		return true;
	}
};

typedef std::list<CMemoryBlock*> LIST_MEMBLOCK;
typedef std::shared_ptr<CMemoryBlock> MB_Ptr;
//typedef std::list<MB_Ptr>    LIST_MsgBase;
typedef std::queue<MB_Ptr>    LIST_MsgBase;

class CMessageQueueSh{
public:
	CMessageQueueSh(void) {
		_lTotalBlock=0;
		unsigned int  num=MAX_MEM_NUM;
		//HD_DEBUG("------","MESSAGE  Create1:%u \n",num);
		//Create(num);
	}

	~CMessageQueueSh(void) {
		Destroy();
	}
	int	Create(const unsigned int nPoolSize) {
		return 0;
	}
	void Destroy() {
		int nsize=GetMsgSizeQueUsed();
		while(nsize>0){
			auto pMessage = GetMessageQueUsed();
			SubmitMessageQueUnuse(pMessage);
			nsize=GetMsgSizeQueUsed();
		}
		return;
	}
	int GetMsgSizeQueUsed() {
		int size= 0;
		//boost::mutex::scoped_lock(_mtxUsed);
		_mtxUsed.lock();
		if(!_listMessageUsed.empty()){
			size=_listMessageUsed.size();
		}
		_mtxUsed.unlock();
		return size;
	}
	int GetMsgSizeQueUnUsed() {
		int size= 0;
		//boost::mutex::scoped_lock(_mtxUsed);
		_mtxUnuse.lock();
		if(!_listMessageUnuse.empty()){
			size=_listMessageUnuse.size();
		}
		_mtxUnuse.unlock();
		return size;
	}
	//��ȡ��Ϣ
	MB_Ptr GetMessageQueUnuse(void) {
		int nsize= 0;
		MB_Ptr pMessage=nullptr;
		_mtxUnuse.lock();
		nsize=_listMessageUnuse.size();
		if ( nsize> 0){
			pMessage=std::move(_listMessageUnuse.front());
			_listMessageUnuse.pop();
		}else{
            if(_lTotalBlock>MAX_MEM_NUM){
                log_print(LOG_DBG,"_listMessageUnuse  too long ,something Wrong using:%u _lTotalBlock:%d unuse:%d\n",GetMsgSizeQueUsed(),_lTotalBlock,_listMessageUnuse.size());
                _mtxUnuse.unlock();
                return nullptr  ;
            }
			pMessage=std::move(std::make_shared< CMemoryBlock>(MAX_MSG_LEN));
			_lTotalBlock++;
		}
		_mtxUnuse.unlock();
		return pMessage  ;
	}
	//��ȡ��Ϣ
	MB_Ptr GetMessageQueUsed(void) {
		MB_Ptr pMessage = nullptr;
		int nsize=0;
		//boost::mutex::scoped_lock(_mtxUsed);
		//HD_DEBUG("----","_listMessageUnuse  GetMessageQueUsed:%d,uint:%u \n",_listMessageUsed.size(),_listMessageUsed.size());
		_mtxUsed.lock();
		nsize=_listMessageUsed.size();
		if(_listMessageUsed.empty()||nsize<1){
			log_print(LOG_DBG, "GetMessageQueUsed -------------- empt\n");
			_mtxUsed.unlock();
			return nullptr  ;
		}
		if (nsize>0) {
			pMessage = std::move(_listMessageUsed.front());
			//pMessage=_listMessageUsed.front();
			_listMessageUsed.pop();
		}
		_mtxUsed.unlock();
		return pMessage  ;
	}
	//�ύ��Ϣ
	int SubmitMessageQueUnuse(MB_Ptr pMsg) {
		if (nullptr==pMsg) {
			log_print(LOG_DBG, "SubmitMessageQueUnuse failed message pMsg=nullptr\n");
			return -1;
		}
		//boost::mutex::scoped_lock(_mtxUnuse);
		_mtxUnuse.lock();
		_listMessageUnuse.push(std::move(pMsg));
		_mtxUnuse.unlock();
		return 0;
	}

	//�ύ��Ϣ
	int SubmitMessageQueUsed(MB_Ptr pMsg) {
		if (nullptr==pMsg) {
			log_print(LOG_DBG, "SubmitMessage failed message pMsg=nullptr\n");
			return -1;
		}
		//boost::mutex::scoped_lock(_mtxUsed);
		_mtxUsed.lock();
		_listMessageUsed.push(std::move(pMsg));
		_mtxUsed.unlock();
		return 0;
	}
private:

	bool	_bExitWait;
	unsigned int	_lTotalBlock;
	LIST_MsgBase        _listMessageUsed;
	LIST_MsgBase        _listMessageUnuse;
	//boost::lock_guard<boost::mutex> lck(_mtx);
	//boost::mutex _mtxUsed;
	//boost::mutex _mtxUnuse;
	std::mutex _mtxUsed;
	std::mutex _mtxUnuse;
};

#pragma pack(pop)
#endif